#include <platform/debug.h>
#include <platform/cpu.h>
#include <platform/interrupt.h>
#include <xbook/debug.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>

/*
color fmt: \e[b;fm

Foreground colors
    30	Black
    31	Red
    32	Green
    33	Yellow
    34	Blue
    35	Magenta
    36	Cyan
    37	White
        
Background colors
    40	Black
    41	Red
    42	Green
    43	Yellow
    44	Blue
    45	Magenta
    46	Cyan
    47	White
*/

char *printk_msg[] = {
    "\e[0;35m",     /* Magenta */
    "\e[0;31m",     /* Red */
    "\e[0;33m",     /* Yellow */
    "\e[0;34m",     /* Blue */
    "\e[0;32m",     /* Green */
    "\e[0;37m",     /* White */
    0,
};
/* no color */
#define DEBUG_NONE_COLOR    "\e[0m"

int printk_level = DEFAULT_LOG_LEVEL;

//停机并输出大量信息
void panic(const char *fmt, ...)
{
	char buf[256];

	/* 4 is the size of fmt in the stack */
	va_list arg = (va_list)((char*)&fmt + 4);

	vsprintf(buf, fmt, arg);

	pr_emerg("\npanic: %s", buf);
	disable_intr();
	while(1){
		cpu_idle();
	}
}

//断言
void assertion_failure(char *exp, char *file, char *baseFile, int line)
{
	printk(KERN_ERR "\nassert(%s) failed:\nfile: %s\nbase_file: %s\nln: %d",
	exp, file, baseFile, line);

	spin("assertion failure()");
}

//停机显示函数名
void spin(char * functionName)
{
	printk(KERN_NOTICE "spinning in %s", functionName);
	disable_intr();
	while(1){
		cpu_idle();
	}
}

void debug_putstr(char *str, int count)
{
    while (count-- > 0 && *str){
        debug_putchar(*str++);
    }
}

/**
 * printk - 格式化输出
 * @fmt: 格式
 * @...: 参数
 * 
 * 返回缓冲区长度
 */
int printk(const char *fmt, ...)
{
    unsigned long flags;
    save_intr(flags);
	int i;
	char buf[256];
    memset(buf, 0, 256);
	va_list arg = (va_list)((char*)(&fmt) + 4); /*4是参数fmt所占堆栈中的大小*/
	i = vsprintf(buf, fmt, arg);

    int count = i;
    char *p = buf;
    
    int level = -1;
    char show = 1;

    /* 如果显示指明调试等级 */
    if (*p == '<') {
        /* 有完整的调试等级 */
        if (*(p + 1) >= '0' && *(p + 1) <= (DEFAULT_LOG_MAX + '0') && *(p + 2) == '>') {
            level = *(p + 1) - '0'; /* 获取等级 */
            if (level > printk_level) /* 如果等级过低，就不显示 */ 
                show = 0;
            
            /* move print start ptr */
            p += 3;
            count -= 3;
        }
    }
    if (show) {
        
        /* print level first */
        if (level >= 0) {
            char *q = printk_msg[level];
            // 发送颜色代码
            debug_putstr(q, strlen(q));
        } else { /* 默认颜色 */
            debug_putstr(DEBUG_NONE_COLOR, 4);    
        }
        
        debug_putstr(p, count);
        /* 清除颜色 */
        debug_putstr(DEBUG_NONE_COLOR, 4);    
    }
    restore_intr(flags);
	return i;
}
